package com.xiaouyudeguang.common.filter;

import com.xiaouyudeguang.common.constants.Headers;
import com.zlyx.easy.core.utils.StringUtils;
import com.zlyx.easy.security.authentication.token.AuthenticationToken;
import com.zlyx.easy.security.defaults.filter.DefaultAuthenticationFilter;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.oauth2.common.util.OAuth2Utils;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public abstract class AbstractAuthenticationFilter extends DefaultAuthenticationFilter {

    public static final String CLIENT_SECRET = "client_secret";

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
        String grantType = request.getParameter(Headers.GRANT_TYPE);
        String tenantId = request.getParameter(Headers.TENANT_ID);
        if (StringUtils.isBlank(tenantId)) {
            throw new AuthenticationServiceException("tenant_id is null");
        }
        String clientId = request.getParameter(Headers.CLIENT_ID);
        if (StringUtils.isBlank(clientId)) {
            throw new AuthenticationServiceException("client_id is null");
        }

        String clientSecret = request.getParameter(Headers.CLIENT_SECRET);
        if (StringUtils.isBlank(clientId)) {
            throw new AuthenticationServiceException("client_id is null");
        }
        Object principal = request.getParameter("principal");
        if (principal == null) {
            throw new AuthenticationServiceException("principal is null");
        }

        AuthenticationToken authenticationToken = crateAuthentication(principal, grantType, tenantId, clientId, clientSecret);

        // 将请求参数全部塞到authenticationToken中备用
        authenticationToken.setParams(request.getParameterMap());
        authenticationToken.setDetails(authenticationDetailsSource.buildDetails(request));
        return this.getAuthenticationManager().authenticate(authenticationToken);
    }

    @Override
    public boolean requiresAuthentication(HttpServletRequest request, HttpServletResponse response) {
        String grantType = request.getParameter(OAuth2Utils.GRANT_TYPE);
        logger.debug("grantType = {} ", grantType);
        return isMatch(grantType) && super.requiresAuthentication(request, response);
    }

    public abstract boolean isMatch(String grantType);

    public abstract AuthenticationToken crateAuthentication(Object principal, String grantType, String tenantId, String clientId, String clientSecret);
}
